/*
 * @Copyright: Copyright (C) AMCAX, All rights reserved.
 * @Author: 殷建峰
 * @Date: 2025-02-05 14:17:30
 * @LastEditTime: 2025-02-25 15:59:54
 * @LastEditors: 殷建峰
 * @Description:
 */
import { useDocumentStore, useRenderStore } from '@/common/store';
import { nmAppDebugLog, nmAppErrorLog, nmAppLog } from '@/common/utils';
import { basic, handleSocketEvent } from '@/domain';
import { AntDesignTheme, FeatureManager } from '@amcax/base';
import {
  AmcaxRender,
  CameraManager,
  EntityInfo,
  EntityManager,
  InteractionManager,
} from '@amcax/web-render';
import { ConfigProvider } from 'antd';
import { ManagerId } from 'nextcae-base';
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import ColorBar from '../ColorBar';
import { CSS2DObjectReactRenderer } from '../Css2dReactObject/CSS2DObjectReactRenderer';
import showLoading from '../Loading';
import { ViewCube } from '../ViewCube';
import ReloadModal from './ReloadModal';

const StyleLayout = styled.div`
  width: 100%;
  height: 100%;
  background: linear-gradient(
    180deg,
    #d3e1ef 0%,
    #eceef0 25.52%,
    rgba(236, 238, 240, 0.7) 43.23%,
    rgba(236, 238, 240, 0) 100%
  );
`;

const MemoizedViewCube = memo(ViewCube);
const ViewCubeSize = 180;
export default function Playground() {
  const playgroundRef = useRef<HTMLDivElement>(null);
  const [showViewCube, setShowViewCube] = useState<boolean>(false);
  const [showReloadModal, setShowReloadModal] = useState<boolean>(false);
  const { mainRenderer, setMainRenderer } = useRenderStore();
  const hideLoading = useRef<() => void>(null);

  const onStatusChanged = (open: boolean) => {
    if (!open) {
      if (FeatureManager.isFeatureEnabled('web')) {
        // socket服务连接关闭/断开后，显示ReloadModal
        setShowReloadModal(true);
      } else {
        if (!hideLoading.current) {
          hideLoading.current = showLoading();
        }
      }
    }
  };
  const initData = useCallback(async () => {
    // 打开文档
    await basic.openDocument();

    // 获取模型树
    const modelTreeInfo = await basic.getObjects();
    useDocumentStore.getState().setModelTreeInfo(modelTreeInfo);

    // 请求加载模型渲染数据，后端会分批推送geometryRender事件过来，统一在handleSocketEvent中处理了
    await basic.renderData([]);
  }, []);
  const init = useCallback(async () => {
    nmAppLog('init');
    if (!playgroundRef.current) {
      return;
    }
    const cameraManager = new CameraManager(playgroundRef.current);
    const interactionManager = new InteractionManager(playgroundRef.current);

    // 创建相关的mananger
    const geometryMgr: EntityManager = new EntityManager(ManagerId.Geometry);
    const meshMgr: EntityManager = new EntityManager(ManagerId.Mesh);
    const assisMgr: EntityManager = new EntityManager(ManagerId.Assis);

    // 将实体管理器绑定到交互管理器；Assis如果需要交互，也可以添加进去
    interactionManager.bindToEntityManager(meshMgr);

    interactionManager.addHoveredListener((entityInfo: EntityInfo) => {
      nmAppDebugLog('last hovered:', entityInfo);
    });
    interactionManager.addClickListener((entityInfo: EntityInfo) => {
      nmAppDebugLog('selected:', entityInfo);
    });
    // 暂时禁用框选和单选
    interactionManager.enableBoxSelect = false;
    interactionManager.enablePick = false;
    interactionManager.pickType = [];
    // interactionManager.addBoxSelectListener(
    //   (selectedEntities: EntityInfo[]) => {
    //     console.log('boxSelected:', selectedEntities);
    //   },
    // );
    // 实例化AmcaxRender
    const amcaxRender = new AmcaxRender(
      playgroundRef.current!,
      cameraManager,
      interactionManager,
    );
    // 将实体管理器添加到AmcaxRender中
    amcaxRender.addEntityManger(geometryMgr, meshMgr, assisMgr);
    // 渲染
    amcaxRender.render();

    // amcaxRender.showAxisHelper();

    setMainRenderer(amcaxRender);

    try {
      // 注册事件监听
      await basic.registerEventHandler(handleSocketEvent);
      // 添加连接状态监听
      await basic.addStatusListener(onStatusChanged);

      // 设置二进制解析函数
      await basic.setDecodeBinaryDataFunc();

      // 监听electron 的 service state 变化
      if (window['electronAPI']) {
        nmAppDebugLog('window.electronAPI', window['electronAPI']);
        window['electronAPI'].onServiceState((data) => {
          nmAppDebugLog('NextShape 服务状态:', data);
          if (data?.state === 'ready') {
            hideLoading.current?.();
            initData().then(() => {
              nmAppDebugLog('init data done');
            });
          } else if (data?.state === 'stop') {
            basic.stop();
            if (!hideLoading.current) {
              hideLoading.current = showLoading();
            }
          }
        });
      }

      await initData();
    } catch (error) {
      nmAppErrorLog(error);
    }
  }, []);
  useEffect(() => {
    init().then(() => {
      nmAppLog('init loaded');
      setShowViewCube(true);
    });
    return () => {
      basic.unregisterEventHandler(handleSocketEvent).then(() => {
        nmAppDebugLog('注销事件监听');
      });

      basic.removeStatusListener(onStatusChanged).then(() => {
        nmAppDebugLog('移除连接状态监听');
      });

      mainRenderer?.dispose();
    };
  }, [init]);
  return (
    <ConfigProvider theme={AntDesignTheme}>
      <div
        style={{
          position: 'relative',
          width: '100%',
          height: '100%',
        }}>
        <StyleLayout
          id='playground'
          ref={playgroundRef}>
          <CSS2DObjectReactRenderer />
        </StyleLayout>
        {showViewCube && (
          <div
            style={{
              position: 'absolute',
              top: 0,
              right: 0,
              width: `${ViewCubeSize}px`,
              height: `${ViewCubeSize}px`,
            }}>
            <MemoizedViewCube
              camera={mainRenderer?.cameraManager.camera}
              controls={mainRenderer?.cameraManager.controls}
              fitView={async () => {
                await mainRenderer?.cameraManager.fitView(true, [0.4, -1, 0.6]);
              }}
              size={ViewCubeSize}
            />
          </div>
        )}
        <ColorBar />
        <ReloadModal open={showReloadModal} />
      </div>
    </ConfigProvider>
  );
}
